package com.cskaoyan.wordmemorize.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cskaoyan.wordmemorize.common.constant.ResultCodeEnum;
import com.cskaoyan.wordmemorize.common.exception.BusinessException;
import com.cskaoyan.wordmemorize.converter.PayConverter;
import com.cskaoyan.wordmemorize.dao.entity.*;
import com.cskaoyan.wordmemorize.dao.mapper.*;
import com.cskaoyan.wordmemorize.dto.admin.PageDTO;
import com.cskaoyan.wordmemorize.dto.app.PayOrderDTO;
import com.cskaoyan.wordmemorize.dto.app.VocPaySaleDTO;
import com.cskaoyan.wordmemorize.request.PageRequest;
import com.cskaoyan.wordmemorize.request.PaySuccessNotifyCommand;
import com.cskaoyan.wordmemorize.request.VocPaySaleCommand;
import com.cskaoyan.wordmemorize.service.UserPayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.Date;
import java.util.List;


@Service
public class UserPayServiceImpl implements UserPayService {
    @Autowired
    PayConverter payConverter;
    @Autowired
    UserMapper userMapper;
    @Autowired
    VocPaySaleMapper vocPaySaleMapper;
    @Autowired
    GoodsMapper goodsMapper;
    @Autowired
    UserVocBoundStatisticsMapper userVocBoundStatisticsMapper;
    @Autowired
    UserVocBoundLogMapper userVocBoundLogMapper;

    @Override
    public PayOrderDTO pay(VocPaySaleCommand command, Long userId) {
        // todo:判断本次交易是否是购买补签卡,若goodsDO.Type为3则为补签卡
        GoodsDO goodsDO = goodsMapper.selectById(command.getItemId());
        if (3 == goodsDO.getType()) {
            // todo:查询用户是否已有补签卡,0表示没有补签卡，1表示有补签卡
            if (1 == userMapper.selectById(userId).getHasSignCard()) {
                // todo:若用户已有补签卡，抛出异常，用户已经有补签卡，不能重复购买
                throw new BusinessException(ResultCodeEnum.USER_ALREADY_OWN_RESIGN_CARD);
            }
        }
        // todo:保存本次支付交易至数据库
        VocPaySaleDO vocPaySaleDO = payConverter.vocPaySaleCommand2DO(command);
        vocPaySaleDO.setUserId(userId);
        vocPaySaleDO.setStatus(1);
        int affectedRow = vocPaySaleMapper.insert(vocPaySaleDO);
        if (1 != affectedRow) {
            throw new BusinessException(ResultCodeEnum.FAIL);
        }

        return payConverter.vocPaySaleDO2PayOrderDTO(vocPaySaleDO);
    }

    @Override
    public String paySuccess(PaySuccessNotifyCommand command, Long userId) {

        VocPaySaleDO vocPaySaleDO = vocPaySaleMapper.selectById(command.getId());
        Integer itemType = vocPaySaleDO.getItemType();
        String itemName = vocPaySaleDO.getItemName();
        Integer value = goodsMapper.selectById(vocPaySaleDO.getItemId()).getValue();

        switch (itemType) {
            case 1: {
                // todo:交易类型为单词上限时,增加总单词上限，购买单词上限，可用单词上限
                LambdaUpdateWrapper<UserVocBoundStatisticsDO> userVocBoundStatisticsDOUpdateWrapper = new LambdaUpdateWrapper<>();
                userVocBoundStatisticsDOUpdateWrapper.eq(UserVocBoundStatisticsDO::getUserId, userId)
                        .setSql("total = total + " + value)
                        .setSql("pay = pay + " + value)
                        .setSql("available = available + " + value);
                userVocBoundStatisticsMapper.update(userVocBoundStatisticsDOUpdateWrapper);

                // todo:在voc_bound_log表中新增一条单词上限变更记录
                userVocBoundLogMapper.insert(UserVocBoundLogDO.builder()
                        .userId(userId)
                        .paySaleId(command.getId())
                        .logDate(LocalDate.now())
                        .type(1)
                        .count(value)
                        .description(itemName)
                        .build());
                break;
            }
            case 2: {
                // todo:交易类型为等级解锁时
                String levelName = vocPaySaleDO.getItemName();
                LambdaUpdateWrapper<UserDO> userDOUpdateWrapper = new LambdaUpdateWrapper<>();
                userDOUpdateWrapper.eq(UserDO::getId, userId)
                        .set(UserDO::getLevelName, levelName)
                        .set(UserDO::getLevelValue, value)
                        .set(UserDO::getLevelDate, LocalDate.now());
                userMapper.update(userDOUpdateWrapper);
                break;
            }
            case 3: {
                // todo:交易类型为补签卡时 在购买前的pay方法中已经判断用户是否有补签卡了
                // todo:这里已经购买完成，经过pay的判断，能执行到这里的用户肯定没有补签卡，直接将hasSignCard设为1
                LambdaUpdateWrapper<UserDO> userDOUpdateWrapper = new LambdaUpdateWrapper<>();
                userDOUpdateWrapper.eq(UserDO::getId, userId)
                        .set(UserDO::getHasSignCard, 1);
                userMapper.update(userDOUpdateWrapper);
                break;
            }
        }
        // todo:修改订单状态status为2，支付成功
        LambdaUpdateWrapper<VocPaySaleDO> vocPaySaleDOUpdateWrapper = new LambdaUpdateWrapper<>();
        vocPaySaleDOUpdateWrapper
                .eq(VocPaySaleDO::getId, command.getId())
                .set(VocPaySaleDO::getStatus, 2);
        vocPaySaleMapper.update(vocPaySaleDOUpdateWrapper);

        return "success";
    }

    @Override
    public Integer queryTradeStatus(Long paySaleId) {
        VocPaySaleDO vocPaySaleDO = vocPaySaleMapper.selectById(paySaleId);
        return vocPaySaleDO.getStatus();
    }

    @Override
    public PageDTO<VocPaySaleDTO> getPaySaleHistory(Long userId, PageRequest pageRequest) {
        LambdaQueryWrapper<VocPaySaleDO> vocPaySaleQueryWrapper = new LambdaQueryWrapper<>();
        vocPaySaleQueryWrapper.eq(VocPaySaleDO::getUserId, userId);
        List<VocPaySaleDO> vocPaySaleDOS;
        // todo:无参时全表查询
        if (pageRequest == null || pageRequest.getPageNum() == null) {
            vocPaySaleDOS = vocPaySaleMapper.selectList(vocPaySaleQueryWrapper);
            return payConverter.vocPaySalePage2PageDTO(vocPaySaleDOS, (long) vocPaySaleDOS.size());
        }
        // todo：有参时分页查询
        Page<VocPaySaleDO> pageParam = new Page<>(pageRequest.getPageNum(), pageRequest.getCount());
        vocPaySaleDOS = vocPaySaleMapper.selectList(pageParam, vocPaySaleQueryWrapper);
        return payConverter.vocPaySalePage2PageDTO(vocPaySaleDOS, (long) vocPaySaleDOS.size());
    }
}
